package com.gas.gm.pdu;

import org.apache.log4j.Logger;

import com.gas.gm.model.Message;
import com.gas.gm.pdu.handler.BindRequestHandler;
import com.gas.gm.pdu.handler.RequestHandler;
import com.gas.gm.pdu.msg.GasMessageRequestConverter;
import com.gas.gm.pdu.msg.MessageRequestConverter;
import com.gas.gm.pdu.msg.MessageStorage;
import com.gas.gm.pdu.session.GasGmSession;
import com.gas.gm.service.AccountService;
import com.gas.gm.util.ChannelConfigurator;
import com.gas.gm.util.GasContextHelper;
import com.logica.smpp.Data;
import com.logica.smpp.pdu.BindRequest;
import com.logica.smpp.pdu.BindResponse;
import com.logica.smpp.pdu.Request;
import com.logica.smpp.pdu.Response;
import com.logica.smpp.pdu.SubmitMultiSM;
import com.logica.smpp.pdu.SubmitMultiSMResp;
import com.logica.smpp.pdu.SubmitSM;
import com.logica.smpp.pdu.SubmitSMResp;

public class MessageDataProcessor extends DataProcessor {

	private static final Logger logger = Logger
			.getLogger(MessageDataProcessor.class);

	private GasGmSession session;

	private AccountService service;
	
	private MessageStorage storage;

	private String systemId;

	private boolean bound = false;
	
	private MessageRequestConverter converter;

	public MessageDataProcessor(GasGmSession session,MessageStorage storage) {
		this.session = session;
		this.service = GasContextHelper.getApplicationContext().getBean(AccountService.class);
		this.storage=storage;
		this.converter=new GasMessageRequestConverter();
	}

	@Override
	public void processRequest(Request cRequest) throws Exception {
		logger.info("process request: " + cRequest.debugString());
		Response response;
		int commandStatus;
		int commandId = cRequest.getCommandId();

		if (!bound)// bind dulu kaka...
		{
			if (commandId == Data.BIND_RECEIVER|| commandId == Data.BIND_TRANSMITTER|| commandId == Data.BIND_TRANSCEIVER) {
				commandStatus = validate((BindRequest) cRequest);
				if (commandStatus == 0) {
					BindResponse bindResponse = (BindResponse) cRequest
							.getResponse();
					bindResponse.setSystemId(SYSTEM_ID);
					session.sendPdu(bindResponse);
					bound = true;
				} else {
					response = cRequest.getResponse();
					response.setCommandStatus(cRequest.getCommandStatus());
					session.sendPdu(response);
					session.stop();
				}
			} else {
				if (cRequest.canResponse()) {
					response = cRequest.getResponse();
					response.setCommandStatus(Data.ESME_RINVBNDSTS);
					session.sendPdu(response);
				}
				session.stop();
			}
		} else {// udah bound
			if (cRequest.canResponse()) {
				response = cRequest.getResponse();
				switch (commandId) {
				case Data.SUBMIT_SM:
					SubmitSMResp submitSMResp=(SubmitSMResp) response;
					Message message=constructMessage((SubmitSM) cRequest);
					submitSMResp.setMessageId(message.getSystemId());
					storage.add(message);
					break;
				case Data.SUBMIT_MULTI:
					SubmitMultiSMResp multiSMResp=(SubmitMultiSMResp) response;
					Message[] messages=constructMultiMessage((SubmitMultiSM) cRequest);
					logger.info("constructed message: "+messages[0].toString());
					multiSMResp.setMessageId(messages[0].getSystemId());
					for(int i=0;i<messages.length;i++){
						storage.add(messages[i]);
					}
					break;
				case Data.UNBIND:
					break;
				}
				session.sendPdu(response);
				if(commandId==Data.UNBIND){
					session.stop();
				}
			}else{
				
			}
		}

	}

	public String getSystemId() {
		return systemId;
	}

	@Override
	public void processResponse(Response cResponse) throws Exception {
		// TODO Auto-generated method stub

	}

	protected int validateAccount(BindRequest request) {
		ProcessorValidator validator = new AccountProcessorValidator(service);
		int commandStatus = validator.validate(request);
		if (commandStatus == Data.ESME_ROK) {
			systemId = request.getSystemId();
		} else {
			systemId = null;
		}
		return commandStatus;

	}
	
	protected int validate(BindRequest request){
		RequestHandler handler=new BindRequestHandler();
		int commandStatus=handler.validateBindRequest(request);
		if(commandStatus==Data.ESME_ROK){
			systemId = request.getSystemId();
		} else {
			systemId = null;
		}
		return commandStatus;
		
	}
	
	protected Message constructMessage(SubmitSM request){
		Message message=converter.composeSingleMessage(request);
		message.setSystemId(systemId);
		
		return message;
	}
	
	protected Message[] constructMultiMessage(SubmitMultiSM request){
		int addcount=request.getNumberOfDests();
		Message[] messages = new Message[addcount];
		for(int i=0;i<messages.length;i++)
		{
			messages[i]=new Message();
			messages[i].setSystemId(systemId);
			messages[i].setServiceType(request.getServiceType());
			messages[i].setSourceAddress(request.getSourceAddr().getAddress());
			messages[i].setDestinationAddress(request.getDestAddress(i).getAddress().getAddress());
			messages[i].setShortMessage(request.getShortMessage());
			messages[i].setMessageChannel(ChannelConfigurator.fix(messages[i].getDestinationAddress()));
		}
		return messages;
	}

	public GasGmSession getSession() {
		return session;
	}
	
	
	
	

}
